#pragma once

#include <DbgHelp.h>
#include <functional>
#include <gtl/thread/lambda.h>

#pragma comment(lib, "Dbghelp.lib")

namespace gtl
{

class dump
{
public:
	template<class Callback>
	static void initialize(const gtl::tstr& save_path, Callback& callback)
	{
		static gtl::tstr sv_path = save_path;
		static Callback clback = callback;

		SetUnhandledExceptionFilter(gtl::lambda<long (__stdcall*)(PEXCEPTION_POINTERS)>([=](PEXCEPTION_POINTERS pExceptionInfo) -> long {
			CreateDirectory(sv_path, NULL);

			gtl::tstr filepath = gtl::path() / sv_path / (gtl::tstr(_T("dump_")) << GetTickCount() << _T(".dmp"));
			HANDLE hDumpFile = CreateFile(filepath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

			MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
			dumpInfo.ExceptionPointers = pExceptionInfo;
			dumpInfo.ThreadId = GetCurrentThreadId();
			dumpInfo.ClientPointers = TRUE;
			MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

			CloseHandle(hDumpFile);

			if(callback(filepath, pExceptionInfo))
				return EXCEPTION_EXECUTE_HANDLER;

			return EXCEPTION_CONTINUE_SEARCH;
		}));
	}
};

} // end of namespace gtl